export function convertLogTimeStringToStamp(timeString) {
    let ymdEnd = timeString.lastIndexOf('-');
    let hmssEnd = timeString.lastIndexOf('.');
    let ymd = timeString.substring(0, ymdEnd);
    let hmss = timeString.substring(ymdEnd + 1, hmssEnd);
    let us = timeString.substring(hmssEnd + 1).padStart(3, '0')
    // 从当前的日志来看，如果ms和us不足三位数，会在前面补0,不过为了防止以后啰嗦，这里也兼容没补0的情况
    return parseFloat(Date.parse(ymd + "T" + hmss + "Z") + '.' + us);
}

/**
 * 将日志中的dateString和timeString转换成数字
 * @param dateString 格式：2023-01-01
 * @param timeString 格式：10:40:20.220.150
 * @returns {number}
 */
export function convertLogDateTimeStringToTimestamp(dateString, timeString) {
    return convertLogTimeStringToStamp(dateString + '-' + timeString);
}

export function convertTimestampToObj(timestamp) {
    let d = new Date(Math.floor(timestamp));
    return {
        year: d.getUTCFullYear(),
        month: (d.getUTCMonth() + 1).toString().padStart(2, '0'),
        day: d.getUTCDate().toString().padStart(2, '0'),
        hour: d.getUTCHours().toString().padStart(2, '0'),
        minute: d.getUTCMinutes().toString().padStart(2, '0'),
        second: d.getUTCSeconds().toString().padStart(2, '0'),
        ms: d.getUTCMilliseconds().toString().padStart(3, '0'),
        us: Math.round((timestamp % 1) * 1000).toString().padStart(3, '0')
    }
}

export class DateFormatter {
    constructor(formatString) {
        this.formatString = formatString;
    }
    #samePrefixLen(s1, s2, start) {
        let compareLen = Math.min(s1.length, s2.length - start)
        for (let i = 0; i < compareLen; ++i) {
            if (s1[i] !== s2[start + i]) {
                return i;
            }
        }
        return compareLen;
    }
    #matchObj(obj, s, start) {
        let matched = [];
        for (let keyAndValue of Object.entries(obj)) {
            let matchLen = this.#samePrefixLen(keyAndValue[0], s, start);
            if (matchLen !== 0) {
                matched.push({
                    formatString: s.substring(start, start + matchLen),
                    key: keyAndValue[0],
                    value: keyAndValue[1]
                });
            }
        }

        let longestMatches = [];
        for (let oneMatched of matched) {
            if (longestMatches.length === 0) {
                longestMatches.push(oneMatched);
            } else {
                if (longestMatches[0].formatString.length < oneMatched.formatString.length) {
                    longestMatches = [oneMatched];
                } else if (longestMatches[0].formatString.length === oneMatched.formatString.length) {
                    longestMatches.push(oneMatched);
                }
            }
        }
        if (longestMatches.length === 0) {
            return null;
        }
        if (longestMatches.length === 1) {
            return longestMatches[0];
        }
        throw new SyntaxError("Ambiguous format string " + this.formatString
            + " at position " + start + ", multiple key matches: " + matched.map(e => e.key));
    }
    format(timestamp) {
        let timeObj = convertTimestampToObj(timestamp);
        let formatIndex = 0;
        let resultString = "";
        while (formatIndex < this.formatString.length) {
            let matched = this.#matchObj(timeObj, this.formatString, formatIndex);
            if (matched === null) {
                resultString += this.formatString[formatIndex++];
            } else {
                resultString += matched.value;
                formatIndex += matched.formatString.length;
            }
        }
        return resultString;
    }
}

export function convertTimestampToLogString(timestamp) {
    return {
        date: new DateFormatter("year-month-day").format(timestamp),
        time: new DateFormatter("hour:min:sec.ms.us").format(timestamp)
    }
}